#pragma once

namespace xs
{

class RendererImpl: public Renderer
{
public:
	RendererImpl(): lost_device(false), m_tex_filter(TF_POINT){}

//=================================================================================================
// Main Functions
//=================================================================================================
	virtual void						init(void *hwnd, unsigned int width, unsigned int height, bool fullscreen, 
													const wchar_t *caption, bool antialiasing);
	virtual void						drop();
	virtual bool						get_event(Event &event);

//=================================================================================================
// Gfx Functions
//=================================================================================================

	void								render_batch();

	virtual bool						begin_scene(const Color &background = 0, const RenderTarget &rt = 0);
	virtual bool						end_scene();
		
	unsigned int						first_empty_texture_slot();
	virtual Texture						get_texture(const wchar_t* filename);
	virtual void						remove_texture(const Texture &id);
	void								get_texture_size(const Texture &texture, int &width, int &height);
	void								set_texture_filter(u32 filter);

	virtual RenderTarget				create_render_target(int width, int height);
	virtual Texture						get_render_target_texture(RenderTarget render_target);
	
	void								set_projection(float width, float height);
	void								look_at(float x, float y, float rot);

	void								scissor(int x, int y, int width, int height);

	virtual void						render_quad(const Quad &quad);

//=================================================================================================
// Helper class creation
//=================================================================================================

	virtual FontPtr						create_font(const wchar_t *name);
	virtual ParticleSystem*				create_particle_system(const ParticleSystemDesc &desc);
	virtual SpritePtr					create_sprite(const Texture &texture);

//=================================================================================================
// System Manipulation
//=================================================================================================

	virtual void						set_window_caption(const wchar_t* name);
	
	virtual void						show_cursor(bool show);

protected:
	void								load_texture(const wchar_t *filename, const Texture &texture);
	void								on_reset_device();

private:


//=================================================================================================
// Batching
//=================================================================================================

	std::vector<Vertex>					m_vertices;
	std::vector<unsigned long>			m_indices;
	Texture								m_current_texture;
	Blend								m_current_blend;

//=================================================================================================
// Main Variables
//=================================================================================================

	IDirect3DDevice9*					device;
	IDirect3D9*							D3D;
	HWND								hWindow;
	D3DPRESENT_PARAMETERS				d3dpp;

	bool								fullscreen;
	bool								lost_device;
	bool								antialiasing;

	IDirect3DSurface9*					back_buffer;
	bool								current_is_back_buffer;

	u32									m_tex_filter;

//=================================================================================================
// Resources
//=================================================================================================

	struct render_target_t
	{
		IDirect3DSurface9*	surf;
		Texture				texture;
	};

	struct texture_description
	{
		bool			is_render_target;
		std::wstring	filename;
		int				width, height;
		bool			empty;
		RenderTarget	rt;
	};

	std::vector<Texture>				empty_texture_slots;
	std::vector<IDirect3DTexture9*>		textures;
	std::vector<texture_description>	texture_desc;
	std::vector<render_target_t>		render_targets;
	std::map<std::wstring, Texture>		loaded_textures;
};

}